package jwlee.testreflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

public class Reflection {

	/**
	 * 取得参数对象中的公共属性
	 * 
	 * @param obj
	 * @param fieldname
	 * @return
	 * @throws Exception
	 */
	public Object getProperty(Object obj, String fieldname) throws Exception {
		Object result = null;
		Class objClass = obj.getClass();
		Field field = objClass.getField(fieldname);
		result = field.get(obj);
		return result;
	}

	/**
	 * 获得某类的静态属性
	 * 
	 * @param className
	 * @param fieldName
	 * @return
	 * @throws Exception
	 */
	public Object getStaticProperty(String className, String fieldName)
			throws Exception {
		Class cls = Class.forName(className);
		Field field = cls.getField(fieldName);
		Object provalue = field.get(cls);
		return provalue;
	}

	/**
	 * 获取参数对象的属性值
	 * 
	 * @param obj
	 * @param propertyName
	 * @return
	 * @throws Exception
	 */
	public Object getPrivatePropertyValue(Object obj, String propertyName)
			throws Exception {
		Class cls = obj.getClass();
		Field field = cls.getDeclaredField(propertyName);
		field.setAccessible(true);
		Object retvalue = field.get(obj);
		return retvalue;
	}

	/**
	 * 执行某对象的方法
	 * 
	 * @param owner
	 * @param methodName
	 * @param args
	 * @return
	 * @throws Exception
	 */
	public Object invokeMethod(Object owner, String methodName, Object[] args)
			throws Exception {
		Class cls = owner.getClass();
		Class[] argclass = new Class[args.length];
		for (int i = 0, j = argclass.length; i < j; i++) {
			argclass[i] = args[i].getClass();
		}
		Method method = cls.getMethod(methodName, argclass);
		return method.invoke(owner, args);
	}

	/**
	 * 执行静态类的方法
	 * 
	 * @param className
	 * @param methodName
	 * @param args
	 * @return
	 * @throws Exception
	 */
	public Object invokeStaticMethod(String className, String methodName,
			Object[] args) throws Exception {
		Class cls = Class.forName(className);
		Class[] argclass = new Class[args.length];
		for (int i = 0, j = argclass.length; i < j; i++) {
			argclass[i] = args[i].getClass();
		}
		Method method = cls.getMethod(methodName, argclass);
		return method.invoke(null, args);
	}

	public Object newInstance(String className, Object[] args) throws Exception {
		Class clss = Class.forName(className);

		Class[] argclass = new Class[args.length];
		for (int i = 0, j = argclass.length; i < j; i++) {
			argclass[i] = args[i].getClass();
		}
		java.lang.reflect.Constructor cons = clss.getConstructor(argclass);
		return cons.newInstance(args);
	}

	/**
	 * srcVO中get出属性set到desVO里
	 * 
	 * @param srcVO
	 * @param desVO
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public void vo2vo(Object srcVO, Object desVO)
			throws IllegalArgumentException, IllegalAccessException,
			InvocationTargetException {
		Method getMethods[] = srcVO.getClass().getMethods();
		Method setMethods[] = desVO.getClass().getMethods();

		Map setMethodMap = new HashMap();
		for (int i = 0; i < setMethods.length; i++) {
			String setMethodName = setMethods[i].getName();
			String attributeName = setMethodName.substring(3).trim();// set后面部分，
			// 首字母小写
			attributeName = attributeName.substring(0, 1).toLowerCase()
					+ attributeName.substring(1);
			Class declarClass = setMethods[i].getDeclaringClass();
			Constructor constructors[] = declarClass.getConstructors();
			if (setMethodName.startsWith("set") && constructors.length != 0
					&& !declarClass.isInterface()
					&& !attributeName.equals("lrSj")
					&& !attributeName.equals("xgSj")) {
				setMethodMap.put(setMethodName, setMethods[i]);
			}
		}
		for (int j = 0; j < getMethods.length; j++) {
			String getMethodName = getMethods[j].getName();
			if (getMethodName.startsWith("get")) {
				String rSetMethodName = getMethodName
						.replaceFirst("get", "set");
				if (setMethodMap.containsKey(rSetMethodName)) {
					Method setMethod = (Method) setMethodMap
							.get(rSetMethodName);
					Object value = getMethods[j].invoke(srcVO, new Object[0]);
					if (value != null
							&& setMethod.getParameterTypes()[0]
									.isAssignableFrom(value.getClass())) {
						setMethod.invoke(desVO, new Object[] { value });
					}
				}
			}
		}
	}

	public static void main(String[] args) {
		Reflection r = new Reflection();

		RefPojo1 a = new RefPojo1();
		RefPojo2 b = new RefPojo2();
		a.setAttr1(1);
		a.setAttr2("ss");
		a.setAttr3(Calendar.getInstance());

		try {
			for (Field f : RefPojo1.class.getDeclaredFields()) {
				Object value = r.getPrivatePropertyValue(a, f.getName());
				System.out.println(f.getName() + " : " + value);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			r.vo2vo(a, b);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println(b);
	}
}
